//
//  ImageUploader.swift
//  swift_review
//
//  Created by Andrew on 2024/11/26.
//

import Foundation

/// 图片上传管理类
class ImageUploader {
    
    /// 上传单张图片
    /// - Parameters:
    ///   - urlString: 上传接口的 URL
    ///   - image: 要上传的图片数据
    ///   - fileName: 图片文件名
    ///   - completion: 上传结果回调（成功返回数据，失败返回错误）
    func uploadSingleImage(
        urlString: String,
        image: Data,
        fileName: String,
        completion: @escaping (Result<Data, Error>) -> Void
    ) {
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "Invalid URL", code: 400, userInfo: nil)))
            return
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        
        // 创建 HTTP 请求体
        let boundary = UUID().uuidString
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        let body = createMultipartBody(boundary: boundary, images: [image], fileNames: [fileName])
        
        let task = URLSession.shared.uploadTask(with: request, from: body) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
                let error = NSError(domain: "HTTP Error", code: httpResponse.statusCode, userInfo: nil)
                completion(.failure(error))
                return
            }
            
            if let data = data {
                completion(.success(data))
            } else {
                completion(.failure(NSError(domain: "No Data", code: 404, userInfo: nil)))
            }
        }
        
        task.resume()
    }
    
    /// 上传多张图片
    /// - Parameters:
    ///   - urlString: 上传接口的 URL
    ///   - images: 要上传的图片数据数组
    ///   - fileNames: 图片文件名数组（与图片一一对应）
    ///   - completion: 上传结果回调（成功返回数据，失败返回错误）
    func uploadMultipleImages(
        urlString: String,
        images: [Data],
        fileNames: [String],
        completion: @escaping (Result<Data, Error>) -> Void
    ) {
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "Invalid URL", code: 400, userInfo: nil)))
            return
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        
        // 创建 HTTP 请求体
        let boundary = UUID().uuidString
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        let body = createMultipartBody(boundary: boundary, images: images, fileNames: fileNames)
        
        let task = URLSession.shared.uploadTask(with: request, from: body) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
                let error = NSError(domain: "HTTP Error", code: httpResponse.statusCode, userInfo: nil)
                completion(.failure(error))
                return
            }
            
            if let data = data {
                completion(.success(data))
            } else {
                completion(.failure(NSError(domain: "No Data", code: 404, userInfo: nil)))
            }
        }
        
        task.resume()
    }
    
    /// 创建 `multipart/form-data` 请求体
    /// - Parameters:
    ///   - boundary: 分隔符
    ///   - images: 图片数据数组
    ///   - fileNames: 文件名数组
    /// - Returns: 构造完成的请求体数据
    private func createMultipartBody(boundary: String, images: [Data], fileNames: [String]) -> Data {
        var body = Data()
        
        for (index, image) in images.enumerated() {
            body.append("--\(boundary)\r\n".data(using: .utf8)!)
            let fileName = fileNames[index]
            body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
            body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
            body.append(image)
            body.append("\r\n".data(using: .utf8)!)
        }
        
        body.append("--\(boundary)--\r\n".data(using: .utf8)!)
        return body
    }
}
